package schedule

import (
	_ "fmt"
	"util"
)

// 包头
type SQuantTradingPacketHead struct {
	WPid      uint16 //包ID
	DwBodyLen uint32 //包体字节数
}

const QTPacketHeadSize = 6

func (s *SQuantTradingPacketHead) EnCode() []byte {
	var b []byte
	b = append(b, util.Uint16ToByte(s.WPid)...)
	b = append(b, util.Uint32ToByte(s.DwBodyLen)...)
	return b
}

func (s *SQuantTradingPacketHead) DeCode(b []byte) {
	s.WPid = util.Byte2Uint16(b[:2])
	s.DwBodyLen = util.Byte2Uint32(b[2:6])
}

type IEnCode interface {
	EnCode() []byte
}

type IDeCode interface {
	DeCode(b []byte) error
}

// 保活，无包体
const QUANTTRADING_PID__KEEP_ALIVE = (uint16(100))

// ////////////////////////////////////////////////////////////////////////
//
// ////////////////////////////////////////////////////////////////////////
// 计算用的账户子类型信息
type SQuantTradingStruct_CalcKTypeItem struct {
	//一个用户这三个键，只会出一次结果
	YAccountKType   byte   //子账户类型，1-4分别表示，日线、两小时线、小时线、半小时线。需要和系统中的其他定义保持一致。
	DwCalcTradeDate uint32 //计算的交易日日期YYYYMMDD
	DwCalcBatch     uint32 //该交易日的第几批计算

	DwCalcBatchBeginDate uint32 //这批次计算的有效数据开始日期
	DwCalcBatchBeginTime uint32 //这批次计算的有效数据开始时间
	DwCalcBatchEndDate   uint32 //这批次计算的有效数据截止日期
	DwCalcBatchEndTime   uint32 //这批次计算的有效数据截止时间
}

func (s *SQuantTradingStruct_CalcKTypeItem) DeCode(b []byte) {
	s.YAccountKType = b[0]
	s.DwCalcTradeDate = util.Byte2Uint32(b[1:5])
	s.DwCalcBatch = util.Byte2Uint32(b[5:9])
	s.DwCalcBatchBeginDate = util.Byte2Uint32(b[9:13])
	s.DwCalcBatchBeginTime = util.Byte2Uint32(b[13:17])
	s.DwCalcBatchEndDate = util.Byte2Uint32(b[17:21])
	s.DwCalcBatchEndTime = util.Byte2Uint32(b[21:25])
}

// 计算结果 nCalcResultCode 的取值
const QUANTTRADING_CALCRESULT__UNKNOWN = (int32(0)) //未知

const QUANTTRADING_CALCRESULT__SUCC = (int32(1)) //成功

const QUANTTRADING_CALCRESULT__WAIT = (int32(2)) //计算中,等待计算结果

const QUANTTRADING_INITRDATA__WAIT = (int32(3)) //计算中,等待计算结果

const QUANTTRADING_CALCRESULT__FAIL = (int32(-1)) //失败

// ////////////////////////////////////////////////////////////////////////
//
//	分股票
//
// ////////////////////////////////////////////////////////////////////////
const QUANTTRADING_PID__STKRECOMM__BASE = (uint16(3000))

// 分股票计算
const QUANTTRADING_PID__STKRECOMM_CALC = (QUANTTRADING_PID__STKRECOMM__BASE + 1)

type SQuantTradingBody_StkRecommCalc struct {
	UllQuantCalcPoint  uint64 //计算点，年月日时分秒 20190620103015 表示 '2019-06-20 10:30:15'
	UllQuantCalcExecId uint64 //计算点执行号，每次计算唯一
	//	DwCalcTradeDate    uint32    //计算的交易日日期YYYYMMDD
	Reserve [4]uint32 //保留

	YCalcKTypeItemCount byte
	ArrCalcKTypeItem    []SQuantTradingStruct_CalcKTypeItem
}

func (s *SQuantTradingBody_StkRecommCalc) DeCode(b []byte) {
	s.UllQuantCalcPoint = util.Byte2Uint64(b[:8])
	//fmt.Println(s.UllQuantCalcPoint)
	s.UllQuantCalcExecId = util.Byte2Uint64(b[8:16])
	//fmt.Println(s.UllQuantCalcExecId)
	//	s.DwCalcTradeDate = util.Byte2Uint32(b[16:20])
	//	fmt.Println(s.DwCalcTradeDate)
	s.Reserve[0] = util.Byte2Uint32(b[16:20])
	s.Reserve[1] = util.Byte2Uint32(b[20:24])
	s.Reserve[2] = util.Byte2Uint32(b[24:28])
	s.Reserve[3] = util.Byte2Uint32(b[28:32])
	s.YCalcKTypeItemCount = b[32]
	//fmt.Println(s.YCalcKTypeItemCount)
	s.ArrCalcKTypeItem = make([]SQuantTradingStruct_CalcKTypeItem, s.YCalcKTypeItemCount)
	for i := (byte)(0); i < s.YCalcKTypeItemCount; i++ {
		s.ArrCalcKTypeItem[i].DeCode(b[33+i*25 : 33+(i+1)*25])
	}
}

type SQuantTradingBody_StkRecommCalcA struct {
	UllQuantCalcPoint  uint64    //计算点
	UllQuantCalcExecId uint64    //计算点执行号
	Reserve            [4]uint32 //保留

	NCalcResultCode   int32  //计算结果，0：表示成功，<0失败，>0保留
	NCalcResultMsgLen int32  //计算结果描述信息长度
	SzCalcResultMsg   string //计算结果描述信息
}

func (s *SQuantTradingBody_StkRecommCalcA) EnCode() []byte {
	var b []byte
	b = append(b, util.Uint64ToByte(s.UllQuantCalcPoint)...)
	b = append(b, util.Uint64ToByte(s.UllQuantCalcExecId)...)
	b = append(b, util.Uint32ToByte(s.Reserve[0])...)
	b = append(b, util.Uint32ToByte(s.Reserve[1])...)
	b = append(b, util.Uint32ToByte(s.Reserve[2])...)
	b = append(b, util.Uint32ToByte(s.Reserve[3])...)
	b = append(b, util.Int32ToByte(s.NCalcResultCode)...)
	b = append(b, util.Int32ToByte(s.NCalcResultMsgLen)...)
	b = append(b, []byte(s.SzCalcResultMsg)...)
	return b
}

// 每个计算日，计算之前初始化数据
const QUANTTRADING_PID__STKRECOMM_INIT_CALCDATA = (QUANTTRADING_PID__STKRECOMM__BASE + 2)

type SQuantTradingBody_StkRecommInitCalcData struct {
	DwCalcTradeDate uint32    //计算的交易日日期YYYYMMDD
	Reserve         [4]uint32 //保留
}

func (s *SQuantTradingBody_StkRecommInitCalcData) DeCode(b []byte) {
	s.DwCalcTradeDate = util.Byte2Uint32(b[:4])
	s.Reserve[0] = util.Byte2Uint32(b[4:8])
	s.Reserve[1] = util.Byte2Uint32(b[8:12])
	s.Reserve[2] = util.Byte2Uint32(b[12:16])
	s.Reserve[3] = util.Byte2Uint32(b[16:20])
}

type SQuantTradingBody_StkRecommInitCalcDataA struct {
	DwCalcTradeDate uint32    //计算的交易日日期YYYYMMDD
	Reserve         [4]uint32 //保留

	NCalcResultCode   int32  //计算结果，0：表示成功，<0失败，>0保留
	NCalcResultMsgLen int32  //计算结果描述信息长度
	SzCalcResultMsg   string //计算结果描述信息
}

func (s *SQuantTradingBody_StkRecommInitCalcDataA) EnCode() []byte {
	var b []byte
	b = append(b, util.Uint32ToByte(s.DwCalcTradeDate)...)
	b = append(b, util.Uint32ToByte(s.Reserve[0])...)
	b = append(b, util.Uint32ToByte(s.Reserve[1])...)
	b = append(b, util.Uint32ToByte(s.Reserve[2])...)
	b = append(b, util.Uint32ToByte(s.Reserve[3])...)
	b = append(b, util.Int32ToByte(s.NCalcResultCode)...)
	b = append(b, util.Int32ToByte(s.NCalcResultMsgLen)...)
	b = append(b, []byte(s.SzCalcResultMsg)...)
	return b
}
